// Prevent console window in addition to Slint window in Windows release builds when, e.g., starting the app via file manager. Ignored on other platforms.
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]

use aws_config::BehaviorVersion;
use aws_sdk_s3::Client;
use aws_sdk_s3::config::Credentials;
use chrono::DateTime;
use slint::{Model, StandardListViewItem, VecModel};
use std::rc::Rc;
use std::sync::{LazyLock, OnceLock};

slint::include_modules!();

static RUNTIME: LazyLock<tokio::runtime::Runtime> = LazyLock::new(|| {
    tokio::runtime::Builder::new_multi_thread()
        .enable_all()
        .build()
        .unwrap()
});

static S3: OnceLock<aws_sdk_s3::Client> = OnceLock::new();

async fn get_s3_client() -> aws_sdk_s3::Client {
    let credentials = Credentials::new(
        "AKLTZDJiMDhjYzNmNGEzNDVmMGI4ZmMyYmE4Mjk1ZjRmNWI",
        "WldZMVpHSmpORFl3TURneU5ESTBabUk1WVRZNFpUYzFObU5sTXpGaU5HWQ==",
        None,
        None,
        "tos",
    );

    let shard_config = aws_config::defaults(BehaviorVersion::latest())
        .region("cn-beijing")
        .credentials_provider(credentials)
        .endpoint_url("https://tos-s3-cn-beijing.volces.com")
        .load()
        .await;

    let rustfs_client = Client::new(&shard_config);

    match rustfs_client.list_buckets().send().await {
        Ok(res) => {
            println!("Total buckets number is {:?}", res.buckets().len());
            for bucket in res.buckets() {
                println!("Bucket: {:?}", bucket.name());
            }
        }
        Err(e) => {
            println!("Error listing buckets: {:?}", e);
        }
    }

    rustfs_client
}

fn main() -> anyhow::Result<()> {
    // 初始化s3
    RUNTIME.block_on(async {
        S3.set(get_s3_client().await).unwrap();
    });
    // 初始化上下文
    let mut ctx = s3_client::Context::default();

    let main_window = MainWindow::new()?;

    // 获取文件列表
    let files = RUNTIME
        .block_on(async { get_files().await })?
        .into_iter()
        .map(|file| {
            let col = vec![
                StandardListViewItem::from(file.name.as_str()),
                StandardListViewItem::from("-"),
                StandardListViewItem::from(file.last_modified.to_rfc3339().as_str()),
                StandardListViewItem::from("-"),
            ];
            Rc::new(VecModel::from(col)).into()
        })
        .collect::<Vec<_>>();

    let files_model = Rc::new(VecModel::from(files));

    main_window.set_files(files_model.into());

    main_window.run()?;

    Ok(())
}

async fn get_files() -> anyhow::Result<Vec<s3_client::File>> {
    let res = S3
        .get()
        .unwrap()
        .list_objects_v2()
        .bucket("cyber-cut-test")
        .send()
        .await?;
    let res = res
        .contents()
        .iter()
        .map(|obj| s3_client::File {
            name: obj.key.clone().unwrap_or(String::from("-")),
            last_modified: DateTime::from_timestamp_secs(
                obj.last_modified.unwrap().as_secs_f64() as i64
            )
            .unwrap(),
        })
        .collect::<Vec<_>>();

    Ok(res)
}
